package com.kika.obwiki.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kika.obwiki.entity.User;
import com.kika.obwiki.exception.BusinessException;
import com.kika.obwiki.exception.BusinessExceptionCode;
import com.kika.obwiki.mapper.UserMapper;
import com.kika.obwiki.rep.UserQueryReq;
import com.kika.obwiki.rep.UserResetPasswordReq;
import com.kika.obwiki.rep.UserSaveReq;
import com.kika.obwiki.rep.UserLoginReq;
import com.kika.obwiki.resp.PageResp;
import com.kika.obwiki.resp.UserQueryResp;
import com.kika.obwiki.resp.UserLoginResp;
import com.kika.obwiki.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kika.obwiki.utils.CopyUtil;
import com.kika.obwiki.utils.SnowFlake;
import com.kika.obwiki.utils.SaltUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.List;

/**
 * 用户服务实现类
 * 实现用户管理相关的业务逻辑
 *
 * @author cr
 * @since 2025-06-22
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

  private static final Logger LOG = LoggerFactory.getLogger(UserServiceImpl.class);

  @Autowired
  private SnowFlake snowFlake;

  private static final String PASSWORD_KEY = "123456qwer";

  @Override
  public PageResp<UserQueryResp> listByname(UserQueryReq req) {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    // 第一个参数：该参数是一个布尔类型，只有该参数是true时，才将like条件拼接到sql中；本例中，如果name字段不为空，则拼接name字段的like查询条件；
    queryWrapper.like(StringUtils.isNotBlank(req.getName()), "name", req.getName());
    queryWrapper.or().like(StringUtils.isNotBlank(req.getLoginName()), "login_name", req.getLoginName());

    // 创建分页对象
    Page<User> page = new Page<>(req.getPage(), req.getSize());
    page = this.baseMapper.selectPage(page, queryWrapper);

    List<UserQueryResp> resps = CopyUtil.copyList(page.getRecords(), UserQueryResp.class);
    // 创建返回对象
    PageResp<UserQueryResp> pageResp = new PageResp<>();
    pageResp.setList(resps);
    pageResp.setTotal(page.getTotal());
    return pageResp;
  }

  @Override
  public void save(UserSaveReq req) {
    User user = CopyUtil.copy(req, User.class);
    if (ObjectUtils.isEmpty(req.getId())) {
      // 判断用户名是否已经存在
      User one = this.baseMapper.selectOne(new QueryWrapper<User>().eq("login_name", req.getLoginName()));
      if (ObjectUtils.isEmpty(one)) {
        // 新增
        long id = snowFlake.nextId();
        user.setId(id);
        user.setSalt(req.getSalt());
        this.baseMapper.insert(user);
      } else {
        throw new BusinessException(BusinessExceptionCode.USER_LOGIN_NAME_EXIST);
      }
    } else {
      // 更新
      user.setLoginName(null); // 避免绕过前端修改登录名
      user.setPassword(null); // 不修改密码
      user.setSalt(null);
      this.baseMapper.updateById(user);
    }
  }

  @Override
  public void delete(Long id) {
    this.baseMapper.deleteById(id);
  }

  @Override
  public void resetPassword(UserResetPasswordReq req) {
    User user = CopyUtil.copy(req, User.class);
    user.setSalt(req.getSalt());
    this.baseMapper.updateById(user);
  }

  /**
   * 用户登录业务逻辑
   * 
   * @param req 登录请求参数
   * @return 登录响应数据
   */
  @Override
  public UserLoginResp login(UserLoginReq req) {
    // 1.根据用户名查询用户信息
    User user = this.baseMapper.selectOne(new QueryWrapper<User>().eq("login_name", req.getLoginName()));
    if (ObjectUtils.isEmpty(user)) {
      // 用户名不存在
      LOG.info("用户名不存在, {}", req.getLoginName());
      throw new BusinessException(BusinessExceptionCode.LOGIN_USER_ERROR);
    } else {
      // 前端已经加密，直接用前端密文加salt进行比对
      String dbPassword = DigestUtils.md5DigestAsHex((req.getPassword() + user.getSalt()).getBytes());
      LOG.info("登录调试 - 用户: {}, 前端密文: {}, Salt: {}, 计算出的数据库密码: {}, 实际数据库密码: {}",
          req.getLoginName(), req.getPassword(), user.getSalt(), dbPassword, user.getPassword());
      if (user.getPassword().equals(dbPassword)) {
        // 登录成功
        UserLoginResp userLoginResp = CopyUtil.copy(user, UserLoginResp.class);
        return userLoginResp;
      } else {
        // 密码不对
        LOG.info("密码不对, 输入密码：{}, 数据库密码：{}", req.getPassword(), user.getPassword());
        throw new BusinessException(BusinessExceptionCode.LOGIN_USER_ERROR);
      }
    }
  }
}
